package com.hst.web.common.utils;

import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.util.Map;

import javax.imageio.ImageIO;

import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import net.coobird.thumbnailator.Thumbnails;

@Service
public class ImageUtils {
	static String fold = "../filestore";

	/**
	 * 对图片进行旋转
	 * 
	 * @param src
	 *            被旋转图片
	 * @param angel
	 *            旋转角度
	 * @return 旋转后的图片
	 */
	public static BufferedImage rotate(Image src, int angel) {
		int src_width = src.getWidth(null);
		int src_height = src.getHeight(null);
		// 计算旋转后图片的尺寸
		Rectangle rect_des = calcRotatedSize(new Rectangle(new Dimension(src_width, src_height)), angel);
		BufferedImage res = null;
		res = new BufferedImage(rect_des.width, rect_des.height, BufferedImage.TYPE_INT_RGB);
		Graphics2D g2 = res.createGraphics();
		// 进行转换
		g2.translate((rect_des.width - src_width) / 2, (rect_des.height - src_height) / 2);
		g2.rotate(Math.toRadians(angel), src_width / 2, src_height / 2);

		g2.drawImage(src, null, null);
		return res;
	}

	/**
	 * 计算旋转后的图片
	 * 
	 * @param src
	 *            被旋转的图片
	 * @param angel
	 *            旋转角度
	 * @return 旋转后的图片
	 */
	public static Rectangle calcRotatedSize(Rectangle src, int angel) {
		// 如果旋转的角度大于90度做相应的转换
		if (angel >= 90) {
			if (angel / 90 % 2 == 1) {
				int temp = src.height;
				src.height = src.width;
				src.width = temp;
			}
			angel = angel % 90;
		}

		double r = Math.sqrt(src.height * src.height + src.width * src.width) / 2;
		double len = 2 * Math.sin(Math.toRadians(angel) / 2) * r;
		double angel_alpha = (Math.PI - Math.toRadians(angel)) / 2;
		double angel_dalta_width = Math.atan((double) src.height / src.width);
		double angel_dalta_height = Math.atan((double) src.width / src.height);

		int len_dalta_width = (int) (len * Math.cos(Math.PI - angel_alpha - angel_dalta_width));
		int len_dalta_height = (int) (len * Math.cos(Math.PI - angel_alpha - angel_dalta_height));
		int des_width = src.width + len_dalta_width * 2;
		int des_height = src.height + len_dalta_height * 2;
		return new Rectangle(new Dimension(des_width, des_height));
	}

	/***
	 * 图片镜像处理
	 * 
	 * @param file
	 * @param fx
	 *            0 为上下反转 1 为左右反转
	 * @return
	 */
	public static void imageReverse(String fileName, int fx) {
		try {
			String FilePath = fold + fileName;
			String suffix = FilePath.substring(FilePath.lastIndexOf(".") + 1);
			File file = new File(FilePath);
			BufferedImage bufferedimage = ImageIO.read(file);
			int w = bufferedimage.getWidth();
			int h = bufferedimage.getHeight();

			int[][] datas = new int[w][h];
			for (int i = 0; i < h; i++) {
				for (int j = 0; j < w; j++) {
					datas[j][i] = bufferedimage.getRGB(j, i);
				}
			}
			int[][] tmps = new int[w][h];
			if (fx == 0) {
				for (int i = 0, a = h - 1; i < h; i++, a--) {
					for (int j = 0; j < w; j++) {
						tmps[j][a] = datas[j][i];
					}
				}
			} else if (fx == 1) {
				for (int i = 0; i < h; i++) {
					for (int j = 0, b = w - 1; j < w; j++, b--) {
						tmps[b][i] = datas[j][i];
					}
				}
			}
			for (int i = 0; i < h; i++) {
				for (int j = 0; j < w; j++) {
					bufferedimage.setRGB(j, i, tmps[j][i]);
				}
			}

			ImageIO.write(bufferedimage, suffix, file);

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static void imgsReverse(Map<String, Integer> map, Object obj) throws IllegalAccessException,
			IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException, IOException {
		// 图片旋转处理
		for (Map.Entry<String, Integer> e : map.entrySet()) {
			String img = (String) obj.getClass()
					.getMethod("get" + e.getKey().substring(0, 1).toUpperCase() + e.getKey().substring(1)).invoke(obj);
			if (img != null)
				imageReverse(img, e.getValue());
		}
	}

	public static void imgsRotate(Map<String, Integer> map, Object obj) throws IllegalAccessException,
			IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException, IOException {
		// 图片反转处理
		for (Map.Entry<String, Integer> e : map.entrySet()) {
			String img = (String) obj.getClass()
					.getMethod("get" + e.getKey().substring(0, 1).toUpperCase() + e.getKey().substring(1)).invoke(obj);
			if (img != null)
				imageRotate(img, e.getValue());
		}
	}

	/**
	 * 图片文件旋转
	 * 
	 * @param src
	 *            被旋转的图片文件名
	 * @param angel
	 *            旋转角度
	 * @return
	 */
	public static void imageRotate(String fileName, int angel) throws IOException {
		String FilePath = fold + fileName;
		String suffix = FilePath.substring(FilePath.lastIndexOf(".") + 1);
		try {
			File file = new File(FilePath);
			BufferedImage src = ImageIO.read(file);
			BufferedImage des = rotate(src, angel);
			ImageIO.write(des, suffix, new File(FilePath));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 图片文件压缩
	 * 
	 * @param src
	 *            被压缩的图片文件名
	 * @return
	 */
	public static void imageCommpress(String fileName) throws IOException {
		String FilePath = fold + fileName;
		commpressPicForScale(FilePath, FilePath, 1000, 0.8, 5000, 5000);
	}

	/**
	 * 根据指定大小和指定精度压缩图片
	 * 
	 * @param srcPath
	 *            源图片地址
	 * @param desPath
	 *            目标图片地址
	 * @param desFileSize
	 *            指定图片大小，单位kb
	 * @param accuracy
	 *            精度，递归压缩的比率，建议小于0.9
	 * @param desMaxWidth
	 *            目标最大宽度
	 * @param desMaxHeight
	 *            目标最大高度
	 * @return 目标文件路径
	 */
	@SuppressWarnings("rawtypes")
	public static String commpressPicForScale(String srcPath, String desPath, long desFileSize, double accuracy,
			int desMaxWidth, int desMaxHeight) {
		if (StringUtils.isEmpty(srcPath) || StringUtils.isEmpty(srcPath)) {
			return null;
		}
		if (!new File(srcPath).exists()) {
			return null;
		}
		try {
			File srcFile = new File(srcPath);
			long srcFileSize = srcFile.length();

			if (srcFileSize <= desFileSize * 1024) {
				return desPath;
			}
			// System.out.println("源图片：" + srcPath + "，大小：" + srcFileSize / 1024
			// + "kb");
			// 获取图片信息
			BufferedImage bim = ImageIO.read(srcFile);
			int srcWidth = bim.getWidth();
			int srcHeight = bim.getHeight();

			// 先转换成jpg
			Thumbnails.Builder builder = Thumbnails.of(srcFile).outputFormat("jpg");

			// 指定大小（宽或高超出会才会被缩放）
			if (srcWidth > desMaxWidth || srcHeight > desMaxHeight) {
				builder.size(desMaxWidth, desMaxHeight);
			} else {
				// 宽高均小，指定原大小
				builder.size(srcWidth, srcHeight);
			}

			// 写入到内存
			ByteArrayOutputStream baos = new ByteArrayOutputStream(); // 字节输出流（写入到内存）
			builder.toOutputStream(baos);

			// 递归压缩，直到目标文件大小小于desFileSize
			byte[] bytes = commpressPicCycle(baos.toByteArray(), desFileSize, accuracy);

			// 输出到文件
			File desFile = new File(desPath);
			FileOutputStream fos = new FileOutputStream(desFile);
			fos.write(bytes);
			fos.close();

			// System.out.println("目标图片：" + desPath + "，大小" + desFile.length() /
			// 1024 + "kb");
			// System.out.println("图片压缩完成！");
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
		return desPath;
	}

	private static byte[] commpressPicCycle(byte[] bytes, long desFileSize, double accuracy) throws IOException {
		// File srcFileJPG = new File(desPath);
		long srcFileSizeJPG = bytes.length;
		// 2、判断大小，如果小于500kb，不压缩；如果大于等于500kb，压缩
		if (srcFileSizeJPG <= desFileSize * 1024) {
			return bytes;
		}
		// 计算宽高
		BufferedImage bim = ImageIO.read(new ByteArrayInputStream(bytes));
		int srcWdith = bim.getWidth();
		int srcHeigth = bim.getHeight();
		int desWidth = new BigDecimal(srcWdith).multiply(new BigDecimal(accuracy)).intValue();
		int desHeight = new BigDecimal(srcHeigth).multiply(new BigDecimal(accuracy)).intValue();

		ByteArrayOutputStream baos = new ByteArrayOutputStream(); // 字节输出流（写入到内存）
		Thumbnails.of(new ByteArrayInputStream(bytes)).size(desWidth, desHeight).outputQuality(accuracy)
				.toOutputStream(baos);
		return commpressPicCycle(baos.toByteArray(), desFileSize, accuracy);
	}

	@SuppressWarnings("unused")
	public static void main(String[] args) throws IOException {
		File file = new File("C:\\Users\\SPC\\Pictures\\人员照片.png");

		commpressPicForScale("E:\\照片\\保单照片.png", "E:\\照片\\test1.png", 1000, 0.8, 5000, 5000); // 图片小于1000kb

		// BufferedImage src = ImageIO.read(file);
		// // 顺时针旋转90度
		// BufferedImage des1 = rotate(src, 90);
		// ImageIO.write(des1, "png", new File("d:/90.png"));
		// // 顺时针旋转180度
		// BufferedImage des2 = rotate(src, 180);
		// ImageIO.write(des2, "png", new File("d:/180.png"));
		// // 顺时针旋转270度
		// BufferedImage des3 = rotate(src, 270);
		// ImageIO.write(des3, "png", new File("d:/270.png"));
	}

}
